package com.junrry.communication

import android.Manifest
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.inuker.bluetooth.library.BluetoothClient
import com.inuker.bluetooth.library.Code.REQUEST_SUCCESS
import com.inuker.bluetooth.library.connect.listener.BluetoothStateListener
import com.inuker.bluetooth.library.connect.options.BleConnectOptions
import com.inuker.bluetooth.library.receiver.listener.BluetoothBondListener
import com.inuker.bluetooth.library.search.SearchRequest
import com.inuker.bluetooth.library.search.SearchResult
import com.inuker.bluetooth.library.search.response.SearchResponse
import com.junrry.communication.databinding.ActivityPcBinding
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset
import java.util.UUID


private var PERMISSIONS_REQUIRED = arrayListOf<String>().apply {
    add(Manifest.permission.ACCESS_COARSE_LOCATION)
    add(Manifest.permission.ACCESS_FINE_LOCATION)
}

private const val TAG = "BleActivity_LJM"

class BleActivity : ComponentActivity() {

    private lateinit var binding: ActivityPcBinding

    private lateinit var activityResultLauncher: ActivityResultLauncher<Array<String>>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityPcBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initBle()
        requestPermissions()
        initListener()
    }

    private fun initListener() {
        binding.btnSend.setOnClickListener {
            val data = binding.etSend.text.toString()
            writeData(data)
        }
    }

    private fun requestPermissions() {
        val contract = ActivityResultContracts.RequestMultiplePermissions()
        activityResultLauncher = registerForActivityResult(contract) { result ->
            var permissionGranted = true
            result.entries.forEach {
                if (it.key in PERMISSIONS_REQUIRED && !it.value) permissionGranted = false
            }
            if (!permissionGranted) {
                Toast.makeText(this, "无权限", Toast.LENGTH_LONG).show()
            } else {
                searchDevice()
            }
        }
        activityResultLauncher.launch(PERMISSIONS_REQUIRED.toTypedArray())
    }

    private lateinit var mClient: BluetoothClient
    private val mDevices: MutableList<SearchResult> = ArrayList<SearchResult>()
    private var mDeviceMAC: String = ""
    private val mBluetoothStateListener: BluetoothStateListener =
        object : BluetoothStateListener() {
            override fun onBluetoothStateChanged(openOrClosed: Boolean) {
                if (openOrClosed) searchDevice()
            }
        }

    private val mBluetoothBondListener: BluetoothBondListener = object : BluetoothBondListener() {
        override fun onBondStateChanged(mac: String, bondState: Int) {
            // bondState = Constants.BOND_NONE, BOND_BONDING, BOND_BONDED
        }
    }

    private fun initBle() {
        mClient = BluetoothClient(this)
        mClient.registerBluetoothStateListener(mBluetoothStateListener)
        mClient.registerBluetoothBondListener(mBluetoothBondListener)
    }

    private fun searchDevice() {
        if (!mClient.isBleSupported) {
            Log.d("LJM", "当前设备不支持BLE")
            return
        }
        if (mClient?.isBluetoothOpened == false) {
            mClient.openBluetooth();
//            mClient.closeBluetooth();
            return
        }
        val request = SearchRequest.Builder().searchBluetoothLeDevice(3000, 3) // 先扫BLE设备3次，每次3s
            .searchBluetoothClassicDevice(5000) // 再扫经典蓝牙5s
            .searchBluetoothLeDevice(2000) // 再扫BLE设备2s
            .build()

        mClient?.search(request, mSearchResponse)
    }

    var builder = StringBuilder()
    private val mSearchResponse: SearchResponse = object : SearchResponse {
        override fun onSearchStarted() {
            //开始扫描，可以在此加入一些状态设置。以及一些数据清空处理。
            Log.d("LJM", "MainActivity.onSearchStarted")
            mDevices.clear()
            builder = StringBuilder()
        }

        override fun onDeviceFounded(device: SearchResult?) {

            //监测扫描出的设备是否已经包含在设备数组里
            if (!containsDevice(device)) {
                builder.append(device?.name)
                builder.append("\t")
                builder.append(device?.address)
                builder.append("\n")
                mDevices.add(device!!)
                //给设备Adapter设值
                binding.tvDevice.text = builder.toString()

                if (device?.address?.contains("03:D7:FA") == true) {
                    connect(device.address)
                }
            }
        }

        override fun onSearchStopped() {
            Log.d("LJM", "MainActivity.onSearchStopped")

        }

        override fun onSearchCanceled() {
            Log.d("LJM", "MainActivity.onSearchCanceled")
        }
    }

    private fun containsDevice(device: SearchResult?): Boolean {
        for (d in mDevices) {
            if (d.address == device?.address && d.name == device?.name) {
                return true
            }
        }
        return false
    }

    private fun connect(deviceMAC: String) {
        val options = BleConnectOptions.Builder().setConnectRetry(3) // 连接如果失败重试3次
            .setConnectTimeout(30000) // 连接超时30s
            .setServiceDiscoverRetry(3) // 发现服务如果失败重试3次
            .setServiceDiscoverTimeout(20000) // 发现服务超时20s
            .build()

        mClient.connect(deviceMAC, options) { code, data ->
            Log.d("LJM", "code: $code, data: $data")
            if (code == REQUEST_SUCCESS) {
                val status = mClient.getConnectStatus(deviceMAC)
                mDeviceMAC = deviceMAC
                Log.d("LJM", "status: $status")
                readRssi()
//                readData()

            }

        }
    }

    private fun readData() {
        mClient.read(
            mDeviceMAC,
            UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"),
            UUID.fromString("49535343-1e4d-4bd9-ba61-23c647249616"),
        ) { code, data -> Log.d("LJM", "code: $code, data: $data") }
    }

    private fun readRssi() {
        mClient.readRssi(
            mDeviceMAC
        ) { code, rssi ->
            if (code == REQUEST_SUCCESS) {
                Log.d("LJM", "rssi: $rssi")
            }
        }
    }

    private fun writeData(str: String) {
        Log.d("LJM", "writeData: ${str.toByteArray().size}")

        try {
            mClient.write(
                mDeviceMAC,
                UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"),
                UUID.fromString("49535343-8841-43f4-a8d4-ecbe34729bb3"),
                str.toByteArray(Charset.forName("GBK"))
            ) { code ->
                Log.d("LJM", "code: $code")
            }
        } catch (e: UnsupportedEncodingException) {
            e.printStackTrace();
        }

    }

    private fun close() {
        mClient?.stopSearch()
        mClient?.unregisterBluetoothStateListener(mBluetoothStateListener);
        mClient?.unregisterBluetoothBondListener(mBluetoothBondListener);
    }

    override fun onDestroy() {
        super.onDestroy()
        close()
    }

}